package com.unism.common.aop.sso;

import java.io.*;
import java.net.*;
import java.util.Enumeration;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.*;

import com.unism.common.sso.session.*;
import com.unism.util.StringUtil;
import com.unism.common.sso.commu.udpServer.*;
import com.unism.common.sso.login.SSOCookie;
import com.unism.common.sso.login.SSOReferer;
import com.unism.common.aop.SessionUserHolder;
import com.unism.common.aop.sso.socket.*;
import com.unism.common.aop.sso.help.*;
import com.unism.common.aop.config.AopConfig;

public class SsoFilter implements Filter {

	private static Logger log = LoggerFactory.getLogger(SsoFilter.class.getName());

	// 为DWR框架应用，标识会话过期
	// public static int SESSIONTIMEOUT = 1000 ;

	// 等待登录返回的最大时长
	private static WaitLoginCach waitLoginCach;

	/////////////////////////
	// 非静态变量
	private String error;

	public void destroy() {
	}

	/**
	 * 过滤器初始化
	 */
	public void init(FilterConfig config) throws ServletException {
		// 启动等待登录成功数据缓存线程
		if (!AopConfig.debug) {
			WaitLoginCach.setMaxWaitLoginTime(AopConfig.waitLoginTimeOut);
			waitLoginCach = new WaitLoginCach();
			waitLoginCach.start();

			this.initUdpSocket(0);

			System.out.println("@@@@ Sso client: upd port of send datum:" + AopConfig.udpSendPort + " @@@@");
			System.out.println("@@@@ Sso client: upd port of receive datum:" + AopConfig.udpReceivePort + " @@@@");

			System.out.println("@@@@ Sso client has started. @@@@");
		}
	}

	/**
	 * 启动单点登录的UDP网络连接
	 * 
	 * @param count
	 */
	private void initUdpSocket(int count) throws ServletException {
		try {
			// 启动发送数据UDP socket
			UdpSendManager.initFirst(AopConfig.udpSendPort, AopConfig.udpSendTimeOut);
			UdpSendManager sender = UdpSendManager.singleInstance();
			sender.start();
			// 启动接收数据UDP socket
			UdpReceiveManager.initAndStartFirst(AopConfig.udpReceivePort, AopConfig.udpReceiveTimeOut,
					AopConfig.udpReceiveDataLen);

		} catch (SocketException e) {
			System.out.println("单点登录客户端第" + (count + 1) + "尝试创建UDP(端口号:" + AopConfig.udpSendPort + "失败！！");
			if (count > AopConfig.maxTryTimes) {
				// 尝试次数大于最大限制
				e.printStackTrace();
				throw new ServletException("安全过滤器:启动收发送数据UDP 单点登录通信服务失败！原因：" + e.getMessage(), e);
			} else {
				count++;
				AopConfig.createUdpPort();
				this.initUdpSocket(count);
			}
		} catch (Exception e) {
			e.printStackTrace();
			throw new ServletException("安全过滤器:启动接收数据UDP 单点登录服务失败！", e);
		}
	}

	/**
	 * 过滤
	 */
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		if (!AopConfig.debug) {
			log.debug("进入SsoFilter过滤器。");

			HttpServletRequest hr = (HttpServletRequest) request;
			HttpServletResponse hrs = (HttpServletResponse) response;
			// String path = hr.getServletPath();
			String path = hr.getRequestURI();
			hrs.setHeader("Access-Control-Allow-Origin", "*");
			//headers.add("Access-Control-Allow-Origin", "http://podcastpedia.org"); //allows CORS requests only coming from podcastpedia.org		
			hrs.setHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT");			
			hrs.setHeader("Access-Control-Allow-Headers", "X-Requested-With, Content-Type, X-Codingpedia, Token");
			// Access-Control-Allow-Origin
			hr.setCharacterEncoding("UTF-8");
			String method = hr.getMethod();
			if (method.equals("OPTIONS")) {
				hrs.setStatus(200);
				return;
			}
			Enumeration<String> headers = hr.getHeaderNames();
			while (headers.hasMoreElements()) {
				String string = (String) headers.nextElement();
				System.out.println(string + "------>>>>>>>>>" + hr.getHeaders(string));
			}
			if (this.isNeedFilter(path)) {
				log.debug("需要过滤当前路径：" + path);
				if (this.toFilter(hr, hrs, path)) {
					chain.doFilter(request, response);
				}
			} else {
				log.debug("不需要过滤当前路径：" + path);
				String token = hr.getHeader("Token");

				if (StringUtil.isBlank(token)) {
					log.debug(token);
					hrs.setStatus(401);
				} else {
					if (setLocalUserInfo(token, hr, hrs)) {
						chain.doFilter(request, response);
						// 刷新SSO中的会话
						this.refreshSession(request);
					} else {
						log.debug(token);
						hrs.setStatus(401);
					}
				}
				// chain.doFilter(request, response);
			}
		} else {
			chain.doFilter(request, response);
		}
	}

	private Boolean setLocalUserInfo(String token, HttpServletRequest hr, HttpServletResponse hrs) {
		////////////////////////////////////
		// 首先尝试从会话中得到用户信息
		// 如果得到了，说明用户已经成功登录系统了
		SessionUserVO uvo = (SessionUserVO) hr.getSession().getAttribute(token);
		if (uvo != null) {
			// 用户登录后的正常访问
			// 把用户信息放入线程级的安全控制器中，以备进行权限验证
			SessionUserHolder.setUserInfo(uvo);
			return true;
		}
		//
		uvo = this.getUserInfoFromSSO(token, hr, hrs);
		if (uvo != null) {
			// 用户登录后的正常访问
			// 把用户信息放入线程级的安全控制器中，以备进行权限验证
			SessionUserHolder.setUserInfo(uvo);
			return true;
		}
		return false;
	}

	/**
	 * 判断是否需要验证(会话验证和权限验证)
	 * 
	 * @param path
	 * @return
	 */
	private boolean isNeedFilter(String path) {
		String conUrl = null;
		for (int i = 0; AopConfig.releaseUrl != null && i < AopConfig.releaseUrl.length; i++) {

			conUrl = AopConfig.releaseUrl[i];

			if (conUrl.startsWith("*") || conUrl.endsWith("*")) {
				conUrl = conUrl.replaceAll("\\*", "");
				if (!conUrl.equals(".js") && path.contains(conUrl)) {
					return false;
				}
			} else {
				if (path.endsWith(conUrl)) {
					return false;
				}
			}
		}

		for (int i = 0; AopConfig.controlUrl != null && i < AopConfig.controlUrl.length; i++) {
			if (path.endsWith(AopConfig.controlUrl[i])) {
				return true;
			}
		}

		return false;
	}

	/**
	 * 进行验证
	 * 
	 * @param hr
	 * @param hrs
	 * @param path
	 */
	private boolean toFilter(HttpServletRequest hr, HttpServletResponse hrs, String path)
			throws IOException, ServletException {
		boolean nextFilter = true;
		////////////////////////////////////
		// 首先尝试从会话中得到用户信息
		// 如果得到了，说明用户已经成功登录系统了
		SessionUserVO uvo = (SessionUserVO) hr.getSession().getAttribute(AopConfig.userKey);
		if (uvo != null) {
			// 用户登录后的正常访问
			// 把用户信息放入线程级的安全控制器中，以备进行权限验证
			if (AopConfig.checkPower) {
				SessionUserHolder.setUserInfo(uvo);
			}
			return nextFilter;
		}

		String requestUrl = hr.getRequestURL().toString();
		/////////////////////////////////////
		// 到此，判断当前访问是否为登录返回
		// 如果是成功登录返回，进行成功登录返回的相关操作
		if (requestUrl.indexOf(AopConfig.aopSsoUrlKey) > 0) {
			// 登录成功，返回创建的cookie
			log.debug("登录成功返回。");
			// String waitDataId = hr.getParameter(AopConfig.waitDataIdKey) ;
			String sessionId = hr.getParameter(SSOReferer.sessionId);
			/*
			 * if(waitDataId == null || sessionId == null ||
			 * waitDataId.trim().equals("") || sessionId.trim().equals("") ){
			 * //没有参数，可能人为设置的automicSecureSsoUrlKey访问路径，叫其登录
			 * log.debug("登录成功返回，但URL中无waitDataId和sessionId，重新登录！") ;
			 * this.toSsoLogin(hr , hrs) ; return nextFilter = false ; }else{
			 * WaitLoginData wd = WaitLoginCach.getWaitLoginData(waitDataId) ;
			 * if(wd == null){ //说明等待登录超时了,或者用户登录成功后，在按浏览器的回退按钮到登录页面，
			 * //进行再次登录，这时对应waitDataId的数据已经在第一次登录时清空了.
			 * log.debug("登录成功返回，但等待数据已经清空，重新登录！") ; this.toSsoLogin(hr, hrs) ;
			 * return nextFilter = false ; }else{
			 */
			// 登录成功，转向最初访问的页面URL
			log.debug("登录成功返回，创建cookie并转向原访问URL！");
			// 从SSO得到用户信息

			uvo = this.getUserInfoFromSSO(sessionId, hr, hrs);
			error = null;
			// this.creatCookieAndRedirectReffer(hr, hrs , sessionId ,
			// wd.refererUrl , uvo) ;
			return nextFilter = false;
			// }
			// }
		}

		//////////////////////////////////////////////
		// 到此，会话中没有用户信息，访问也不是登录返回,
		// 得到cookie的信息
		Cookie[] cookies = hr.getCookies();
		if (cookies == null) {
			// 说明用户请求没有cookie，表示用户的当前从未登录，转向SSO登录
			log.debug("当前访问无cookie，转向登录！");
			this.toSsoLogin(hr, hrs);
			return nextFilter = false;
		}
		String sessionId = null;
		String fixedIpUserInfo = null;
		for (int i = 0; i < cookies.length; i++) {
			if (cookies[i].getName().equals(SSOCookie.cookieForever_NameKey)) {
				fixedIpUserInfo = cookies[i].getValue();
				break;
			}
			if (cookies[i].getName().equals(SSOCookie.cookieInstant_NameKey)) {
				sessionId = cookies[i].getValue();
				break;
			}
			if (cookies[i].getName().equals(SSOCookie.cookieLocal_NameKey)) {
				sessionId = cookies[i].getValue();
				break;
			}
		}
		if (sessionId == null && fixedIpUserInfo == null) {
			// 说明不能在cookie中得到会话ID
			// 表示用户在本系统从未登录，转向SSO登录
			log.debug("当前访问的cookie中不存会话sessionId也不存在永久IP的用户信息，重新登录！");
			this.toSsoLogin(hr, hrs);
			return nextFilter = false;
		}

		//////////////////////////////////////////
		// 到此，用户请求中存在cookie，并且cookie有效
		// cookie中存在有固定IP的用户信息
		// cookie是永不过期的(实际为10年，参考下面生成cookie的部分)
		if (fixedIpUserInfo != null) {
			// 当前系统会话中没有用户信息，但cookie有效，
			// 可能存在的情况：永久cookie但用户从未登录系统 或者是 用户已经成功登录其他子系统，
			// 首先尝试从SSO系统中得到用户信息
			// 如果从SSO中得到了用户信息，说明用户已经登录了其他子系统了，在本子系统会话中还没有用户信息，那么把用户信息存在本子系统会话中
			// 如果从SSO中不能得到用户信息，说明用户在所有子系统中都未登录，从用户cookie中得到用户信息，通过SSO直接登录。
			// 这里可能会产生error信息
			String ip = hr.getRemoteAddr();
			uvo = this.getUserInfoFromSSO(ip, hr, hrs);
			if (error == null) {
				if (uvo == null) {
					String[] namePassIp = null;
					String fixedIpUserInfoStr = null;
					try {
						Crypt cry = new Crypt();
						byte[] key = cry.getEasyKey();
						byte[] enBin = cry.hex2Byte(fixedIpUserInfo);
						byte[] de = cry.decode(enBin, key);
						fixedIpUserInfoStr = new String(de);
						namePassIp = fixedIpUserInfoStr.split(";");
					} catch (Exception e) {
						// cookie受到破坏
						log.debug("当前访问的cookie中存在固定IP用户的信息，但cookie受到破坏，重新登录！");
						this.toSsoLogin(hr, hrs);
						return nextFilter = false;
					}
					if (namePassIp == null || namePassIp.length != 3) {
						// cookie受到破坏
						log.debug("当前访问的cookie中存在固定IP用户的信息，但用户的信息受到破坏，重新登录！");
						this.toSsoLogin(hr, hrs);
						return nextFilter = false;
					}
					if (!ip.equals(namePassIp[2])) {
						// 偷的cookie，或者是用户实际IP已经变化了
						log.debug("当前访问的cookie中存在固定IP用户的信息，但当前访问IP与cookie中的用户固定IP不相同，重新登录！");
						this.toSsoLogin(hr, hrs);
						return nextFilter = false;
					} else {
						// 用户从未登录系统，
						// 用户直接登录
						uvo = this.directLoginBySSO(namePassIp[2], hr, hrs, fixedIpUserInfoStr);
						if (error == null) {
							if (uvo == null) {
								// 从SSO系统中未得到信息，
								// 正常原因是SSO系统中 ,当前用户登录已经会话过期,或重新启动了服务器；
								// 其他原因就发生了错误
								log.debug("当前访问存在cookie，但从SSO服务器得不到登录用户对象，重新登录！");
								this.toSsoLogin(hr, hrs);
								nextFilter = false;
							} else {
								// 从sso中得到了用户信息
								nextFilter = true;
							}
						}
					}
				} else {
					// 从sso中得到了用户信息
					nextFilter = true;
				}
			}
		}

		////////////////////////////////////////////
		// 到此，非固定IP用户，用户请求中存在cookie，这个cookie是即时cookie，
		// cookie中存在会话ID(sessionId)，说明用户客户端仍是有效登录状态
		if (sessionId != null && fixedIpUserInfo == null) {
			// 当前系统会话中没有用户信息，但cookie有效，原因：会话过期 或者是 用户已经成功登录其他子系统，
			// 重新从SSO系统中得到用户信息
			// 这里可能会产生error信息
			uvo = this.getUserInfoFromSSO(sessionId, hr, hrs);
			if (error == null) {
				if (uvo == null) {
					// 从SSO系统中未得到信息，
					// 正常原因是SSO系统中 ,当前用户登录已经会话过期,或重新启动了服务器；
					// 其他原因就发生了错误
					log.debug("当前访问存在cookie，但从SSO服务器得不到登录用户对象，重新登录！");
					this.toSsoLogin(hr, hrs);
					nextFilter = false;
				} else {
					// 从sso中得到了用户信息
					nextFilter = true;
				}
			}
		}

		///////////////////////
		// 处理过程中产生错误
		if (error != null) {
			this.redirectShowError(hrs, error);
			error = null;
			nextFilter = false;
		}

		if (!nextFilter) {
			return nextFilter;
		}

		////////////////////////////
		// 把用户信息放入线程级的安全控制器中，以备进行权限验证等其他需要用户信息的功能
		if (uvo != null) {
			if (AopConfig.checkPower) {
				SessionUserHolder.setUserInfo(uvo);
			}
			nextFilter = true;
		}
		return nextFilter;
	}

	/**
	 * 从SSO系统中得到登录后的会话用户信息
	 * 
	 * @param sessionId
	 * @return
	 */
	@SuppressWarnings("finally")
	private SessionUserVO getUserInfoFromSSO(String sessionId, HttpServletRequest rq, HttpServletResponse hrs) {
		SessionUserVO vo = null;
		try {
			UdpSendManager send = UdpSendManager.singleInstance();

			SsoData sd = new SsoData();
			sd.order = SsoOrder.checkLogin;
			sd.sessionId = sessionId;
			sd.data = null;

			UdpData ud = new UdpData();
			ud.id = this.IDCreate();
			ud.timeStamp = System.currentTimeMillis();
			ud.receiveIp = AopConfig.ssoUdpIp;
			ud.receivePort = AopConfig.ssoUdpPort;
			ud.returnIp = AopConfig.localUdpIp;
			ud.returnPort = AopConfig.udpReceivePort;
			ud.obj = sd;

			send.setSendObject(ud);

			UdpReceiveManager receive = UdpReceiveManager.newInstance();
			UdpData rud = receive.getReturnData(ud.id, AopConfig.waitReturnTimeOut);
			if (rud != null) {
				SsoData rsd = (SsoData) rud.obj;
				if (rsd.order.intValue() == SsoOrder.error) {
					// SSO系统发现错误
					error = (String) rsd.data;
					// System.out.println(error) ;///////////////////////////
				} else if (rsd.order.intValue() == SsoOrder.noLogin) {
					// 当前用户的客户端有cookie,但SSO中未有当前用户登录;
					// 原因是用户登录后，服务重新启动，而用户的浏览器没有关闭，
					// 在且在没有关闭的页面中进行系统访问
					// 但这里设置vo为null ,使请求转向登录
					vo = null;
				} else if (rsd.order.intValue() == SsoOrder.logined) {
					vo = (SessionUserVO) rsd.data;
					// 把用户信息存入当前系统会话中
					rq.getSession().setAttribute(sessionId, vo);
				}
			}

		} catch (Exception e) {
			e.printStackTrace();
			log.error(e.getMessage(), e);
		} finally {
			return vo;
		}
	}

	/**
	 * 从SSO系统中得到登录后的会话用户信息
	 * 
	 * @param sessionId
	 * @return
	 */
	@SuppressWarnings("finally")
	private SessionUserVO directLoginBySSO(String sessionId, HttpServletRequest rq, HttpServletResponse hrs,
			String fixedIpUserInfo) {
		SessionUserVO vo = null;
		try {
			UdpSendManager send = UdpSendManager.singleInstance();

			SsoData sd = new SsoData();
			sd.order = SsoOrder.directLogin;
			sd.sessionId = sessionId;
			sd.data = fixedIpUserInfo;

			UdpData ud = new UdpData();
			ud.id = this.IDCreate();
			ud.timeStamp = System.currentTimeMillis();
			ud.receiveIp = AopConfig.ssoUdpIp;
			ud.receivePort = AopConfig.ssoUdpPort;
			ud.returnIp = AopConfig.localUdpIp;
			ud.returnPort = AopConfig.udpReceivePort;
			ud.obj = sd;

			send.setSendObject(ud);

			UdpReceiveManager receive = UdpReceiveManager.newInstance();
			UdpData rud = receive.getReturnData(ud.id, AopConfig.waitReturnTimeOut);
			if (rud != null) {
				SsoData rsd = (SsoData) rud.obj;
				if (rsd.order.intValue() == SsoOrder.error) {
					// SSO系统发现错误
					error = (String) rsd.data;
					// System.out.println(error) ;///////////////////////////
				} else if (rsd.order.intValue() == SsoOrder.noLogin) {
					// 当前用户的客户端有cookie,但SSO中未有当前用户登录;
					// 原因是用户登录后，服务重新启动，而用户的浏览器没有关闭，
					// 在且在没有关闭的页面中进行系统访问
					// 但这里设置vo为null ,使请求转向登录
					// System.out.println("当前用户的客户端有cookie,但SSO中未有当前用户登录,原因是用户登录后，服务重新启动，而用户的浏览器没有关闭,在且在没有关闭的页面中进行系统访问,但这里设置vo为null
					// ,使请求转向登录.") ;///////////////////////////
					vo = null;
				} else if (rsd.order.intValue() == SsoOrder.logined) {
					vo = (SessionUserVO) rsd.data;
					// 把用户信息存入当前系统会话中
					rq.getSession().setAttribute(AopConfig.userKey, vo);
				}
			}

		} catch (Exception e) {
			e.printStackTrace();
			log.error(e.getMessage(), e);
		} finally {
			return vo;
		}
	}

	/**
	 * 转向SSO系统，进行登录
	 *
	 */
	private void toSsoLogin(HttpServletRequest hr, HttpServletResponse hrs) throws ServletException {
		String requestUrl = hr.getRequestURL().toString();
		String servletPath = hr.getServletPath();
		String contextPath = hr.getContextPath();
		String referer = null;
		if (contextPath != null && !contextPath.trim().equals("")) {
			referer = requestUrl.substring(0, requestUrl.indexOf(contextPath)) + contextPath + "/";
			if (AopConfig.contextLevel > 1) {
				if (servletPath.endsWith("/dwr")) {
					// dwr以上下文dwr请求，说明是用dwr框架无刷新请求数据
					// referer += AopConfig.subContext ;
				} else {
					String temp = null;
					try {
						int anchor = requestUrl.indexOf(contextPath) + contextPath.length() + 1;
						if (anchor < requestUrl.length()) {
							temp = requestUrl.substring(anchor, requestUrl.length());
							for (int i = 1; i < AopConfig.contextLevel; i++) {
								anchor = temp.indexOf("/");
								if (anchor > 0 && anchor < temp.length()) {
									referer += temp.substring(0, anchor) + "/";
									temp = temp.substring(anchor + 1, temp.length());
								} else {
									break;
								}
							}
						}
					} catch (Exception e) {

					} finally {
						;
					}
				}
			}
		} else if (contextPath.trim().equals("")) {
			// 根系统部署在ROOT目录中，形成的上下文为""
			if (requestUrl.indexOf(AopConfig.aopSsoUrlKey) > 0) {
				// 说明是打开登录页面，但没有及时登录，使这边的WaitLoginData被清空，再次要求登录时，就构造了这样的URL
				referer = requestUrl.substring(0, requestUrl.indexOf(AopConfig.aopSsoUrlKey));
			} else {
				referer = requestUrl;
			}
		} else {
			referer = requestUrl;
		}
		WaitLoginData wd = new WaitLoginData();
		wd.id = this.IDCreate();
		/**
		 * wd.refererUrl 一定要取 referer值，不能取requestUrl值，
		 * 虽然取了referer值，会登录成功重新定向到web系统根，而取requestUrl值时，会登录成功返回到最初访问页面
		 * 原因是：当用户转向登录页面，而没有及时登录，而等待超时，使得WaitLoginCach
		 * 中的等待数据初清空，这时用户登录成功转回到这里，系统会要求用户再去登录，而这时的
		 * requestUrl将会是用户登录成功能的URL，而不是用户最初的URL，如果这果采用了用户登录成功能的URL 那么系统会死循环登录。
		 */
		wd.refererUrl = referer;
		wd.stamp = System.currentTimeMillis();

		WaitLoginCach.putWaitLoginData(wd.id, wd);

		referer += AopConfig.aopSsoUrlKey + ".action?" + AopConfig.waitDataIdKey + "=" + wd.id;
		String redirectUrl = null;
		String ip = hr.getRemoteAddr();
		if (ip.startsWith(AopConfig.innerNetStartIP)) {
			// 内网IP登录系统
			redirectUrl = AopConfig.ssoLoginUrl + servletPath + "?" + SSOReferer.ParameterReferer + "=" + referer;
		} else {
			// 外网
			redirectUrl = AopConfig.ssoLoginUrlOuter + servletPath + "?" + SSOReferer.ParameterReferer + "=" + referer;
		}

		/**
		 * 判断请求框架类型，不同的请求框架类型，生成不同的后期处理
		 */
		try {
			// struts2以后缀.jQuery请求，说明是用jQuery框架无刷新请求页面
			if (servletPath.endsWith(".jQuery")) {
				hrs.setContentType("text/html;charset=utf-8");
				PrintWriter out = hrs.getWriter();
				out.print("<script language=\"JavaScript\">" + "window.location='" + redirectUrl + "' ;" + "</script>");
				out.close();
				return;
			}
			// else if(servletPath.endsWith("/dwr")){
			// //dwr以上下文dwr请求，说明是用dwr框架无刷新请求数据
			// hrs.setStatus(SESSIONTIMEOUT);
			// PrintWriter out = hrs.getWriter();
			// out.print(redirectUrl);
			// out.close();
			// return;
			// }
			else {
				hrs.sendRedirect(redirectUrl);
			}
		} catch (IOException e) {
			log.error("转向单点登录SSO系统时出错!", e);
		}
	}

	/**
	 * 刚登录成功，创建cookie并返回到最初访问URL
	 * 
	 */
	private void creatCookieAndRedirectReffer(HttpServletRequest hr, HttpServletResponse hrs, String sessionId,
			String referer, SessionUserVO uvo) {
		Cookie cookieLocal = new Cookie(SSOCookie.cookieLocal_NameKey, SSOCookie.cookieLocal_NameValue);
		cookieLocal.setDomain("127.0.0.1");
		cookieLocal.setMaxAge(AopConfig.cookieMaxTime);
		cookieLocal.setPath("/");
		cookieLocal.setValue(sessionId);
		hrs.addCookie(cookieLocal);

		String ip = hr.getRemoteAddr();
		String fixedIp = (uvo == null ? null : (uvo.getFixedIP()));
		boolean createInstantCookie = true;
		if (uvo != null && fixedIp != null && !fixedIp.trim().equals("") && ip.equals(fixedIp)) {
			// 用户有固定IP，并且当前用户访问系统所用的IP与数据库中用户实体的固定IP相同
			try {
				String s = uvo.getName() + ";" + uvo.getPassword() + ";" + uvo.getFixedIP();
				Crypt cry = new Crypt();
				byte[] key = cry.getEasyKey();
				byte[] en = cry.encode(s.getBytes(), key);
				Cookie cookie = new Cookie(SSOCookie.cookieForever_NameKey, SSOCookie.cookieForever_NameValue);
				if (ip.startsWith(AopConfig.innerNetStartIP)) {
					// 内网IP登录系统
					cookie.setDomain(AopConfig.systemDomain);
				} else {
					// 外网
					cookie.setDomain(AopConfig.systemDomainOuter);
				}
				cookie.setMaxAge(AopConfig.cookieMaxTimeForFixedIP);
				cookie.setPath("/");
				cookie.setValue(cry.byte2hex(en));
				hrs.addCookie(cookie);
				createInstantCookie = false;
			} catch (Exception e) {
				createInstantCookie = true;
			}
		}
		if (createInstantCookie) {
			Cookie cookie = new Cookie(SSOCookie.cookieInstant_NameKey, SSOCookie.cookieInstant_NameValue);
			if (ip.startsWith(AopConfig.innerNetStartIP)) {
				// 内网IP登录系统
				cookie.setDomain(AopConfig.systemDomain);
			} else {
				// 外网
				cookie.setDomain(AopConfig.systemDomainOuter);
			}
			cookie.setMaxAge(AopConfig.cookieMaxTime);
			cookie.setPath("/");
			cookie.setValue(sessionId);
			hrs.addCookie(cookie);
		}
		try {
			hrs.sendRedirect(referer);
		} catch (IOException e) {
			log.error("转向原始访问页面时出错!", e);
		}
	}

	/**
	 * 转向显示出错信息
	 *
	 */
	private void redirectShowError(HttpServletResponse hrs, String info) {
		info = "服务器出错，请联系管理员!" + (info == null ? "" : ("出错信息:" + info));
		try {
			hrs.setContentType("text/html;charset=utf-8");
			PrintWriter out = hrs.getWriter();
			out.print("<meta   http-equiv='Content-Type'   content='text/html;   charset=gb2312'>");
			out.print("<body onload=\"showInfo()\"></body><script language=\"JavaScript\">function showInfo(){alert('"
					+ info + "')}</script>");
			out.close();
			return;
		} catch (Exception e) {
			log.error("显示出错信息出错！", e);
		}
	}

	/**
	 * 刷新会话
	 * 
	 * @param sessionId
	 */
	private void refreshSession(ServletRequest request) {
		HttpServletRequest hr = (HttpServletRequest) request;
		Cookie[] cookies = hr.getCookies();
		if (cookies != null) {
			String sessionId = null;
			String fixedIpUserInfo = null;
			for (int i = 0; i < cookies.length; i++) {
				if (cookies[i].getName().equals(SSOCookie.cookieForever_NameKey)) {
					fixedIpUserInfo = cookies[i].getValue();
					break;
				}
				if (cookies[i].getName().equals(SSOCookie.cookieInstant_NameKey)) {
					sessionId = cookies[i].getValue();
					break;
				}
				if (cookies[i].getName().equals(SSOCookie.cookieLocal_NameKey)) {
					sessionId = cookies[i].getValue();
					break;
				}
			}

			if (fixedIpUserInfo != null) {
				String[] namePassIp = null;
				String fixedIpUserInfoStr = null;
				try {
					Crypt cry = new Crypt();
					byte[] key = cry.getEasyKey();
					byte[] enBin = cry.hex2Byte(fixedIpUserInfo);
					byte[] de = cry.decode(enBin, key);
					fixedIpUserInfoStr = new String(de);
					namePassIp = fixedIpUserInfoStr.split(";");
					sessionId = namePassIp[2];
				} catch (Exception e) {
					;
				}
			}
			if (sessionId != null) {
				try {
					UdpSendManager send = UdpSendManager.singleInstance();

					SsoData sd = new SsoData();
					sd.order = SsoOrder.freshSession;
					sd.sessionId = sessionId;
					sd.data = null;

					UdpData ud = new UdpData();
					ud.id = this.IDCreate();
					ud.timeStamp = System.currentTimeMillis();
					ud.receiveIp = AopConfig.ssoUdpIp;
					ud.receivePort = AopConfig.ssoUdpPort;
					ud.obj = sd;

					send.setSendObject(ud);

				} catch (Exception e) {
					log.error(e.getMessage(), e);
				}
			}
		}
	}

	/**
	 * 产生ID
	 * 
	 * @return
	 */
	private synchronized String IDCreate() {
		return "" + System.nanoTime();
	}

}